package com.weiwei.base.application;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.sql.Date;
import java.text.SimpleDateFormat;

import android.content.Context;
import android.os.Build;
import android.util.Log;

import com.weiwei.base.common.FileUtils;
import com.weiwei.base.common.VsBizUtil;
import com.weiwei.base.dataprovider.VsUserConfig;

/**
 * 异常捕捉器
 */
public class CrashHandler implements UncaughtExceptionHandler {

    public static final String TAG = "CrashHandler";
    private Thread.UncaughtExceptionHandler mDefaultHandler; // 系统默认ERROR处理器
    private static CrashHandler INSTANCE;
    private Context mContext;
    private String AndroidDeviceModel; // 手机型号

    public CrashHandler() {
    }

    public static CrashHandler getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new CrashHandler();
        }
        return INSTANCE;
    }

    public void init(Context context, String AndroidDeviceModel) {
        this.mContext = context;
        this.AndroidDeviceModel = AndroidDeviceModel;
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this); // 设置默认的错误处理器为自己
    }

    /**
     * ERROR处理器
     */
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handlerException(ex) && mDefaultHandler != null) {
            // 如果用户没处理交给系统默认处理
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            // 如果用户以处理
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(0);
        }
    }

    /**
     * 输出异常栈
     *
     * @param ex
     * @return
     * @author: xiaozhenhua
     * @data:2013-1-9 下午4:52:10
     */
    private boolean handlerException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        StringBuffer sbf = new StringBuffer();
        sbf.append("device:" + this.AndroidDeviceModel + "\n");
        sbf.append("SDK_INT:" + Build.VERSION.SDK_INT + "\n");
        sbf.append("Build.DEVICE:" + Build.DEVICE + "\n");

        Writer writer = new StringWriter();
        PrintWriter pw = new PrintWriter(writer);
        ex.printStackTrace(pw);
        pw.close();
        String error = writer.toString();
        sbf.append("\n" + error + "\n");

        String uid = VsUserConfig.getDataString(mContext, VsUserConfig.JKey_KcId);
        if (uid != null && !"".endsWith(uid)) {
            assembleError("uid:" + uid + "\n" + (sbf.toString()), "error");
        } else {
            assembleError(sbf.toString(), "error");
        }
        return false;
    }

    /**
     * 提交错误日志给运维服务器
     *
     * @param errorContent
     * @param level
     */
    public static void assembleError(String errorContent, String level) {
        Log.e(TAG, "assembleError = " + errorContent);
        Context mContext = VsApplication.getContext();
        String versionCode = (Build.VERSION.RELEASE + "");
        if (versionCode.length() > 3) {
            versionCode = versionCode.substring(0, 3);
        }

        write("level = " + level + "\n", errorContent);
        VsBizUtil.getInstance().reportList(mContext, errorContent, "program_crashes");
    }

    private static String LOG_FILE_DIR_NAME = "TDLog";

    /**
     * 日志文件保存路径
     */
    public static String LOG_FILE_DIR = FileUtils.getSaveFilePath() + LOG_FILE_DIR_NAME + File.separator;
    private static FileWriter fileWriter = null;

    /**
     * 线程中写入文件
     *
     * @param tag
     * @param format
     */
    private static void write(String tag, String format) {
        // 24小时制
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        String cur = sdf.format(new Date(System.currentTimeMillis()));

        final String titleName = cur + ".txt";
        final String str = cur + "   " + tag + "   " + format + "\n";

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    FileUtils.createFile(LOG_FILE_DIR + titleName);
                    fileWriter = new FileWriter(LOG_FILE_DIR + titleName,
                            true);
                    fileWriter.write(str, 0, str.length());
                    fileWriter.flush();
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {

                }
            }
        }).start();
    }
}
